﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace Foundry.Graphics
{
    public interface IStdShader
    {
        IUniform<Matrix4> Projection { get; }
        IUniform<Matrix4> View { get; }
        IUniform<Matrix4> Model { get; }
        IUniform<Matrix4> ModelViewProjection { get; }
        IUniform<Texture2D> Diffuse { get; }
        IUniform<Texture2D> Normal { get; }
        IUniform<Vector3> LightDirection { get; }
		IUniform<Matrix4> NormalMatrix { get; }
    }


    public class DefaultShader : ShaderProgram, IStdShader
    {
        public IUniform<Matrix4> Projection { get; private set; }
        public IUniform<Matrix4> View { get; private set; }
        public IUniform<Matrix4> Model { get; private set; }
		public IUniform<Matrix4> ModelView { get; private set; }
        public IUniform<Matrix4> ModelViewProjection { get; private set; }
		public IUniform<Matrix4> NormalMatrix { get; private set; }
        public IUniform<Texture2D> Diffuse { get; private set; }
        public IUniform<Texture2D> Normal { get; private set; }
        public IUniform<Vector3> LightDirection { get; private set; }
		
		private static readonly string VertexShaderSource = @"

#version 150

uniform mat4 Projection;
uniform mat4 View;
uniform mat4 Model;
uniform mat4 NormalMatrix;
uniform mat4 ModelViewProjection;

in vec3 Pos;
in vec3 Normal;
in vec2 TexCoord;

out vec3 normal;
out vec2 texcoord;
centroid out vec4 pos;

void main()
{
	vec4 tmp_pos = vec4(Pos, 1) * ModelViewProjection;
	gl_Position = tmp_pos;
	pos = tmp_pos;
	normal = (vec4(Normal, 1) * NormalMatrix).xyz;
	//texcoord = TexCoord;
}
";
		private static readonly string FragmentShaderSource = @"
#version 150

centroid in vec4 pos;
in vec3 normal;
in vec2 texcoord;

const vec3 light_pos = vec3(-4, -4, 4);

out vec4 ColorOut;

void main()
{
	ColorOut = vec4(.4392, .5, 0.5655, 1) * -dot(normalize(light_pos - pos.xyz), normal);
}
";
		
		public DefaultShader(params Shader[] sources)
		{
			foreach(var sh in sources)
				AttachShader(sh);
		}
		
		public DefaultShader(VertexDescriptor desc, params Shader[] sources)
			: base(desc)
		{
			foreach(var sh in sources)
				AttachShader(sh);
		}
		
		
        public DefaultShader()
        {
            var verts = Shader.FromSource<VertexShader>(VertexShaderSource);
            var frag = Shader.FromSource<FragmentShader>(FragmentShaderSource);
            AttachShader(verts);
            AttachShader(frag);

        }
        public DefaultShader(VertexDescriptor desc)
            : base(desc)
        {
            VertexShader verts = Shader.FromSource<VertexShader>(VertexShaderSource);
            FragmentShader frag = Shader.FromSource<FragmentShader>(FragmentShaderSource);
            AttachShader(verts);
            AttachShader(frag);
			
        }

        protected override void OnShaderCompiled()
        {
            base.OnShaderCompiled();
            Projection = GetUniform<Matrix4>("Projection");
            View = GetUniform<Matrix4>("View");
            Model = GetUniform<Matrix4>("Model");
			ModelView = GetUniform<Matrix4>("ModelView");
            ModelViewProjection = GetUniform<Matrix4>("ModelViewProjection");
            Diffuse = GetUniform<Texture2D>("DiffuseMap");
            Normal = GetUniform<Texture2D>("NormalMap");
            LightDirection = GetUniform<Vector3>("LightDirection");
			NormalMatrix = GetUniform<Matrix4>("NormalMatrix");
			
        }
    }
}
